﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Infrastructure.Cache;

namespace Infrastructure.ApiCache
{
    public class ApiCacheForSecondFilter : IActionFilter,IOrderedFilter
    {
        public IMemoryCacheService cacheService { get; set; }

        public int Order => 200;

        public ApiCacheForSecondFilter(IMemoryCacheService cacheService)
        {
            this.cacheService = cacheService;
        }

        public string key;
        public HttpApiCacheForSecondAttribute httpApiCacheForSecondAttribute;

        private static ConcurrentDictionary<string, HttpApiCacheForSecondAttribute> map = new ConcurrentDictionary<string, HttpApiCacheForSecondAttribute>();
        /// <summary>
        /// Action 调用前执行
        /// </summary>
        /// <param name="context"></param>
        public void OnActionExecuting(ActionExecutingContext context)
        {
            string actionid = context.ActionDescriptor.Id;

            string url = context.HttpContext.Request.Path + context.HttpContext.Request.QueryString;

            if (!map.TryGetValue(actionid, out httpApiCacheForSecondAttribute))
            {
                ControllerActionDescriptor controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
                if (controllerActionDescriptor != null)
                {
                    httpApiCacheForSecondAttribute = controllerActionDescriptor.MethodInfo.GetCustomAttribute<HttpApiCacheForSecondAttribute>(inherit: true);
                    map.TryAdd(actionid, httpApiCacheForSecondAttribute);
                }
            }

            if (httpApiCacheForSecondAttribute != null)
            {
                string userToken = context.HttpContext.Request.Headers["authorization"];

                url = url.StartsWith("/api/") ? url.Substring(5) : url;
                url = url.Replace("/", "").Replace("?", "").Replace("=", "").Replace("&", "");
                key = string.Empty;                
                if (httpApiCacheForSecondAttribute.ByUser)
                {
                    if (string.IsNullOrEmpty(userToken)) return;

                    key = $"AC:{userToken}:{url}";
                }
                else
                {
                    key = $"AC:{url}";
                }

                var text = cacheService.Get<string>(key);
                if (!string.IsNullOrWhiteSpace(text))
                {
                    var textContent = new ContentResult();
                    textContent.Content = text;
                    textContent.ContentType = "application/json";
                    context.Result = textContent;
                }
            }
        }
        static JsonSerializerSettings setting = new JsonSerializerSettings
        {
            ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
        };
        /// <summary>
        /// Action 方法调用后，Result 方法调用前执行
        /// </summary>
        /// <param name="context"></param>
        public void OnActionExecuted(ActionExecutedContext context)
        {
            if (httpApiCacheForSecondAttribute != null && !string.IsNullOrWhiteSpace(key))
            {
                if (context.Result is ApiResultExtensions.ApiReturn)
                {
                    var result = context.Result as ApiResultExtensions.ApiReturn;

                    if (result.code == ResultCode.Sucess)
                    {
                        cacheService.Set(key, JsonConvert.SerializeObject(result.Value, setting)
                            , TimeSpan.FromSeconds(httpApiCacheForSecondAttribute.Second));
                    }
                }
            }
        }

    }
}
